// Whether the port should be set or not
func validatePortSpec(diff *schema.ResourceDiff, blockName string) error {
    block := diff.Get(blockName+".0").(map[string]interface{})
    portSpec := block["port_specification"]
    portName := block["port_name"]
    port := block["port"]

    hasPort := (port != nil && port != 0)
    noName := (portName == nil || portName == "")

    if portSpec == "USE_NAMED_PORT" && hasPort {
        return fmt.Errorf("Error in %s: port cannot be specified when using port_specification USE_NAMED_PORT.", blockName)
    }
    if portSpec == "USE_NAMED_PORT" && noName {
        return fmt.Errorf("Error in %s: Must specify port_name when using USE_NAMED_PORT as port_specification.", blockName)
    }

    if portSpec == "USE_SERVING_PORT" && hasPort {
        return fmt.Errorf("Error in %s: port cannot be specified when using port_specification USE_SERVING_PORT.", blockName)
    }
    if portSpec == "USE_SERVING_PORT" && !noName {
        return fmt.Errorf("Error in %s: port_name cannot be specified when using port_specification USE_SERVING_PORT.", blockName)
    }

    return nil
}

func healthCheckCustomizeDiff(_ context.Context, diff *schema.ResourceDiff, v interface{}) error {
    if diff.Get("http_health_check") != nil {
        return validatePortSpec(diff, "http_health_check")
    }
    if diff.Get("https_health_check") != nil {
        return validatePortSpec(diff, "https_health_check")
    }
    if diff.Get("http2_health_check") != nil {
        return validatePortSpec(diff, "http2_health_check")
    }
    if diff.Get("tcp_health_check") != nil {
        return validatePortSpec(diff, "tcp_health_check")
    }
    if diff.Get("ssl_health_check") != nil {
        return validatePortSpec(diff, "ssl_health_check")
    }

    return nil
}

func portDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
    b := strings.Split(k, ".")
    if len(b) > 2 {
        attr := b[2]

        if attr == "port" {
            var defaultPort int64

            blockType := b[0]

            switch blockType {
            case "http_health_check":
                defaultPort = 80
            case "https_health_check":
                defaultPort = 443
            case "http2_health_check":
                defaultPort = 443
            case "tcp_health_check":
                defaultPort = 80
            case "ssl_health_check":
                defaultPort = 443
            }

            oldPort, _ := strconv.Atoi(old)
            newPort, _ := strconv.Atoi(new)

            portSpec := d.Get(b[0] + ".0.port_specification")
            if int64(oldPort) == defaultPort && newPort == 0 && (portSpec == "USE_FIXED_PORT" || portSpec == "") {
                return true
            }
        }
    }

    return false
}
